//Timer.cpp
#include "Timer.h"

hw_timer_t *timer = NULL;

/**
  * @brief  通用定时器初始化,ESP32-S3计数频率80MHZ
  *     f = 80MHZ/psc,t = arr/f
  * @param  arr:定时器自动重装值(54位)
  * @param  psc:定时器分频系数(16位)    0~65535
  * @param  timx_ISR:定时器中断回调函数
  * @note   psc = 80 000 则 T = arr*1ms (psc取不到80000)
  * @retval 无
  */
hw_timer_t *timex_Init(TIMx_INT TIM,uint32_t arr,uint16_t psc,void (*timx_ISR)(void))
{
    timer = timerBegin(TIM,psc,true);
    if (timer != NULL) {
        timerAlarmWrite(timer,arr,true);
        timerAttachInterrupt(timer,timx_ISR,true);
        timerAlarmEnable(timer);
    }
    return timer;
}

//参数重载
hw_timer_t *timex_Init(uint8_t TIM,uint32_t arr,uint16_t psc,void (*timx_ISR)(void))
{
    return timex_Init(static_cast<TIMx_INT>(TIM), arr, psc, timx_ISR);
}






/**
  * @brief  PWM初始化函数
  * @param  pin:PWM引脚
  * @param  channel:PWM通道 0~7
  * @param  frequency:PWM频率,单位Hz
  * @param  resolution:PWM分辨率 1~16,单位bit  8:分辨率范围0~255
  * @retval 无
  */
LedcPwm::LedcPwm(uint8_t pin,uint8_t channel,uint16_t frequency,uint8_t resolution)
    :Channel(channel)
{
    Pins.push_back(pin);
    ledcSetup(channel,frequency,resolution);  //有8个通道
    ledcAttachPin(pin,channel);   /*把对应的通道映射到引脚上*/
}

/**
  * @brief  指定占空比数值
  * @param  duty:占空比数值,范围由ledcSetup函数resolution指定
  * @note   请确保引脚模式没有冲突
  * @retval 无
  */
void LedcPwm::ledcpwm_write(uint8_t duty)
{
    ::ledcWrite(this->Channel,duty);
}

/**
  * @brief  同一个通道可对应多个引脚
  * @param  pin:引脚号
  * @retval 无
  */
void LedcPwm::AttachPins(uint8_t pin)
{
    Pins.push_back(pin);
    ::ledcAttachPin(pin, this->Channel);
}

/**
  * @brief  释放该通道的所有引脚
  * @param  无
  * @retval 无
  */
void LedcPwm::DetachPins()
{
    for (auto pin : Pins) {
        ledcDetachPin(pin);
    }
}

/**
  * @brief  指定通道的音调
  * @param  note:音调
  *     NOTE_C, NOTE_Cs, NOTE_D, NOTE_Eb, NOTE_E, NOTE_F, NOTE_Fs, NOTE_G, NOTE_Gs, NOTE_A, NOTE_Bb, NOTE_B
  * @param  octave:音阶
  *     0~7取值0~7；
  * @retval 无
  */
double LedcPwm::ledcWriteNote(note_t note, uint8_t octave)
{
    return ::ledcWriteNote(this->Channel,note,octave);
}

LedcPwm& LedcPwm::operator=(const LedcPwm &ledcPwm)
{
    if (this != &ledcPwm) {
        //清理当前对象的资源
        for (auto pin : this->Pins) {
            ledcDetachPin(pin);
        }
        //复制源对象的数据
        this->Channel = ledcPwm.Channel;
        this->Pins = ledcPwm.Pins;
        //重新配置硬件
        for (auto pin : this->Pins) {
            ledcAttachPin(pin, this->Channel);
        }
    }

    // 返回当前对象的引用
    return *this;
}

LedcPwm::LedcPwm(const LedcPwm &ledcPwm)
{
    this->Channel = ledcPwm.Channel;
    this->Pins = ledcPwm.Pins;
    
    // 重新配置硬件
    for (auto pin : this->Pins) {
        ledcAttachPin(pin, this->Channel);
    }
}


